#include <Model/Include/Scene.h>

#include <stdlib.h>
#include <time.h>

using namespace Model;

// ========== LIFECYCLE ========== //

Scene::Scene(const int &width, const int &height, Snake* snake)
{
    this->width = width;
    this->height = height;
    this->snake = snake;
    // initializing pseudo-random to create new element's position
    srand( time(NULL) );
    this->renewFreeElement();
}

Scene::~Scene()
{
    delete this->free_element;
}

// ========== OVERLODED OPERATORS ========== //

// ========== METHODS ========== //
bool Scene::checkSnakeCollition()
{
    int x = this->snake->getHeadElement()->getXPosition();
    int y = this->snake->getHeadElement()->getYPosition();

    bool collition = false;

    /// checks collition with the scene limits
    if ( (x < 0) || (y < 0) || (x > this->width - 1) || (y > this->height - 1) )
    {
        collition = true;
    }
    else
    {
        collition = this->snake->checkSelfCollition();
    }
    return collition;
}

bool Scene::checkSnakeVsFreeElement()
{
    int x = this->snake->getHeadElement()->getXPosition();
    int y = this->snake->getHeadElement()->getYPosition();
    bool taken = false;
    if ( ( x == this->free_element->getXPosition() ) && ( y == this->free_element->getYPosition() ) )
    {
        this->snake->addElement(this->free_element);
        this->renewFreeElement();
        taken = true;
    }
    return taken;    
}

void Scene::progress(const int &time_elapsed_ms)
{
    this->snake->move(time_elapsed_ms);
}

// ========== GETTERS ========== //
int Scene::getWidth() const
{
    return this->width;
}

int Scene::getHeight() const
{
    return this->height;
}

const Snake* Scene::getSnake() const
{
    return this->snake;
}

const Element* Scene::getFreeElement() const
{
    return this->free_element;
}

// ========== SETTERS ========== //

// ========== INQUIRY ========== //

// ========== INTERNAL METHODS ========== //
void Scene::renewFreeElement()
{
    int new_x = rand() % this->width;
    int new_y = rand() % this->height;
    this->free_element = new Element(new_x, new_y);
}
